/*
 * Plain.java
 *
 * Created on Feb 25, 2008
 *
 * Copyright(c) 2008 OpenOak Technologies 
 * Licensed under the OpenOak Learning License
 */

package com.openoak.textfield;

import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JRootPane;
import javax.swing.JTextField;

/**
 *  Displays the basic text field which is enhanced for showing messages
 *  to the right, below, or in a linked MessageLabel
 *
 *  @author Steven C. Daniel - Copyright (c) 2008
 *  @author OpenOak Technologies - www.openoak.com
 *  @version 1.0
 */
public class Plain extends JTextField implements FocusListener{

    private MessageLabel attachedMessageLabel;
    private JLabel sideMessageLabel;
    private JLabel bottomMessageLabel;
    private boolean hasAttachedMessageLabel = false;
    private boolean sideMessageLabelInitialized = false;
    private boolean bottomMessageLabelInitialized = false;
    private boolean useBottomMessageLabel = false;
    protected boolean isRequired = false;
    private boolean isRequiredShown = false;
    private JRootPane jRootPane;
    private JLayeredPane jLayeredPane;
    private boolean jLayeredPaneInitialized = false;
    
    
    public Plain() {
        this.addFocusListener(this);
    }
    
    /**
     * Checks to see if the curent text field is empty (null)
     * 
     * @return true if null
     */
    public boolean isNull(){
        String theValue = this.getText();
        if (theValue.length() < 1) {
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * Sets the field as "required" to alert the user when they are leaving
     * a field empty that expects a value.  
     * 
     * @param required true if required, false if not
     */
    public void setRequired(boolean required){
        isRequired = required;
    }
    
    /**
     * Attach a message label to use for displaying messages instead of using
     * the pop-ups
     * 
     * @param myLabel The MessageLabel to attach
     */
    public void attachMessageLabel(MessageLabel myLabel){
        attachedMessageLabel = myLabel;
        hasAttachedMessageLabel = sideMessageLabelInitialized = true;
    }
    
    /**
     * Use a bottom pop-up label instead of the one off to the side
     */
    public void useBottomMessage(){
        useBottomMessageLabel = true;
    }

    /**
     * Displays a message for this text field.  By default a message to the side
     * of the text field will be displayed, unless you tell it to display the
     * message at the bottom using useBotomMessage().  You can also attach a 
     * specific MessageLabel to use with attachMessageLabel(MessageLabel).
     * 
     * @param message The message to display
     */
    public void showMessage(String message){
        if (hasAttachedMessageLabel == true){
            attachedMessageLabel.setMessage(message);
        } else {
            if (useBottomMessageLabel == true) {
                showBottomMessageLabel(message);
            } else {
                showSideMessageLabel(message);
            }
        }
        this.setForeground(Color.BLACK);
    }
    
    /**
     * Works the same as showMessage, but changes the background color of the
     * MessageLabel to yellow
     * 
     * @param message The message to display
     */
    public void showMessageWarning(String message){
        if (hasAttachedMessageLabel == true){
            attachedMessageLabel.setWarningMessage(message);
        } else {
            if (useBottomMessageLabel == true) {
                showBottomMessageLabelWarning(message);
            } else {
                showSideMessageLabelWarning(message);
            }
        }
        this.setForeground(Color.BLACK);
    }
    
    /**
     * Works the same as showMessage, but changes the background color of the
     * MessageLabel to pink
     * 
     * @param message The message to display
     */
    public void showMessageError(String message){
        if (hasAttachedMessageLabel == true){
            attachedMessageLabel.setErrorMessage(message);
        } else {
            if (useBottomMessageLabel == true) {
                showBottomMessageLabelError(message);
            } else {
                showSideMessageLabelError(message);
            }
        }
        this.setForeground(Color.RED);
    }
    
    /**
     * Clears any displayed message and resets the color.  Hides any MessageLabel
     * that was a pop-up
     */
    public void clearMessage(){
        if (hasAttachedMessageLabel == true){
            attachedMessageLabel.clearMessage();
        } else {
            if (useBottomMessageLabel == true) {
                hideBottomMessageLabel();
            } else {
                hideSideMessageLabel();
            }
        }
        if (isRequired && (this.getText().length() == 0)) {
           initializeSideMessangeLabel();
           
            sideMessageLabel.setLocation(this.getX() + this.getWidth(), this.getY());
            sideMessageLabel.setSize(5, this.getHeight());
            sideMessageLabel.setBackground(Color.YELLOW);
            sideMessageLabel.setOpaque(true);
            sideMessageLabel.setText("");
        }
        this.setForeground(Color.BLACK);
    }
    public void setText(String text, boolean forceNoMessage){
        super.setText(text);
        if(forceNoMessage){
            clearMessage();
        }
    }
    /**
     * Shows a message on the right side of the text field.
     * 
     * @param message The message to display
     */
    public void showSideMessageLabel(String message) {
        
        initializeSideMessangeLabel();
         
        /*
         * We're adding this to a panel that does not have a layout manager so
         * we need to get the width for the message to reset the size of the JLabel.
         * Otherwise, it will show up as zero width and not be visiable.
         */
        FontMetrics metrics = sideMessageLabel.getFontMetrics(sideMessageLabel.getFont());
        int myStringWidth = metrics.stringWidth(message);
        
        sideMessageLabel.setLocation(this.getX() + this.getWidth(), this.getY());
        sideMessageLabel.setSize(myStringWidth + 4, this.getHeight());
        sideMessageLabel.setHorizontalAlignment(JLabel.CENTER);
        sideMessageLabel.setVerticalAlignment(JLabel.CENTER);
        sideMessageLabel.setOpaque(true);
        sideMessageLabel.setBackground(jRootPane.getBackground());
        sideMessageLabel.setText(message);
        this.setForeground(Color.BLACK);
    }
    
    /**
     * Shows a Warning message on the right side of the text field.
     * 
     * @param message The message to display
     */
    public void showSideMessageLabelWarning(String message){
        showSideMessageLabel(message);
        sideMessageLabel.setBackground(Color.YELLOW);
        this.setForeground(Color.BLACK);
    }
    
    /**
     * Shows an Error message on the right side of the text field.
     * 
     * @param message The message to display
     */
    public void showSideMessageLabelError(String message){
        showSideMessageLabel(message);
        sideMessageLabel.setBackground(Color.PINK);
        this.setForeground(Color.RED);
    }
    
    /**
     * Hides the message label on the right side of the text field
     */
    public void hideSideMessageLabel(){
        /*
         * We're hiding this JLable by setting it's size to (0,0) and 
         * making it transparent.
         */
        if (sideMessageLabelInitialized == true) {
            sideMessageLabel.setSize(0, 0);
            sideMessageLabel.setOpaque(false);
            sideMessageLabel.setBackground(jRootPane.getBackground());
            sideMessageLabel.setText("");
        }
        this.setForeground(Color.BLACK);
    }
    
    /**
     * Shows a message below the text field.
     * 
     * @param message The message to display
     */
    public void showBottomMessageLabel(String message) {
        
        initializeButtonMessangeLabel();
            
        FontMetrics metrics = bottomMessageLabel.getFontMetrics(bottomMessageLabel.getFont());
        int myStringWidth = metrics.stringWidth(message);
        
        bottomMessageLabel.setLocation(this.getX() + this.getHeight(), this.getY() + this.getHeight());
        bottomMessageLabel.setSize(myStringWidth + 4, metrics.getHeight());
        bottomMessageLabel.setHorizontalAlignment(JLabel.CENTER);
        bottomMessageLabel.setVerticalAlignment(JLabel.TOP);
        bottomMessageLabel.setOpaque(true);
        bottomMessageLabel.setBackground(jRootPane.getBackground());
        bottomMessageLabel.setText(message);
        this.setForeground(Color.BLACK);
    }
    
    /**
     * Shows a Warning message below the text field.
     * 
     * @param message The message to display
     */
    public void showBottomMessageLabelWarning(String message){
        showBottomMessageLabel(message);
        bottomMessageLabel.setBackground(Color.YELLOW);
        this.setForeground(Color.BLACK);
    }
    
    /**
     * Shows an Error message below the text field.
     * 
     * @param message The message to display
     */
    public void showBottomMessageLabelError(String message){
        showBottomMessageLabel(message);
        bottomMessageLabel.setBackground(Color.PINK);
        this.setForeground(Color.RED);
    }
    
    /**
     * Hides the message below the text field.
     */
    public void hideBottomMessageLabel(){
        if (bottomMessageLabelInitialized == true) {
            bottomMessageLabel.setSize(0, 0);
            bottomMessageLabel.setOpaque(false);
            bottomMessageLabel.setBackground(jRootPane.getBackground());
            bottomMessageLabel.setText("");
        }
        this.setForeground(Color.BLACK);
    }
    
    /**
     * Sets up the JRootPane and JLayeredPane for use.  
     */
    private void initializePane(){
        /*
         * This only needs to be done once so check to see if we're already 
         * set up before proceeding.
         */
        if (jLayeredPaneInitialized == false) {
            jRootPane = this.getRootPane();
            if(jRootPane!=null){
                jLayeredPane = jRootPane.getLayeredPane();
                jLayeredPane.setOpaque(true);
                jLayeredPaneInitialized = true; 
            }
        }
    }
    
     /**
     * Sets up the sideMessangeLabel for use.  
     */
    private void initializeSideMessangeLabel(){
         /*
         * We only need to add the JLabel once.  Once it's set up we can just hide
         * and re-use it as needed.
         */
        initializePane();
        if (sideMessageLabelInitialized == false) {
            sideMessageLabel = new JLabel();
            jLayeredPane.add(sideMessageLabel, new Integer(10));
            sideMessageLabelInitialized = true;
        } else if(hasAttachedMessageLabel){
            sideMessageLabel = attachedMessageLabel;
        }
    }
    
     /**
     * Sets up the sideMessangeLabel for use.  
     */
    private void initializeButtonMessangeLabel(){
         /*
         * We only need to add the JLabel once.  Once it's set up we can just hide
         * and re-use it as needed.
         */
        initializePane();
        if (bottomMessageLabelInitialized == false) {
            bottomMessageLabel = new JLabel();
            jLayeredPane.add(bottomMessageLabel, new Integer(10));
            bottomMessageLabelInitialized = true;
        } else if(hasAttachedMessageLabel){
            bottomMessageLabel = attachedMessageLabel;
        }
    }
    public void focusGained(FocusEvent arg0) {
        if (isRequiredShown) {
            if (sideMessageLabelInitialized == false && bottomMessageLabelInitialized == true) {
                 hideBottomMessageLabel();
            } else {
                 hideSideMessageLabel();
            }
            isRequiredShown = false;
        }
        renderValidText();
    }

    public void focusLost(FocusEvent arg0) {
        if (isRequired && (this.getText().trim().length() < 1)) {
            if (sideMessageLabelInitialized == false && bottomMessageLabelInitialized == true) {
                initializeButtonMessangeLabel();
                showBottomMessageLabelError("i18n.required");
            } else {
                initializeSideMessangeLabel();
                showSideMessageLabelError("i18n.required");
            }
            isRequiredShown = true;
        } else {
            if (!isRequiredShown) {
                if (sideMessageLabelInitialized == false && bottomMessageLabelInitialized == true) {
                     initializeButtonMessangeLabel();
                     hideBottomMessageLabel();
                } else {
                     initializeSideMessangeLabel();
                     hideSideMessageLabel();
                }
                isRequiredShown = false;
            }
        }
        if(isValidText()){
            this.setForeground(Color.BLACK);
        }
       
    }
    public boolean isValidText(){
        return true;
    }
    public void renderValidText(){
      if(isValidText()){
            this.setForeground(Color.GREEN);
        } else {
            this.setForeground(Color.RED);
        }  
    }
  

}
